package server

import (
	"errors"
	"gitee.com/yangzx6606/core/pattern"
	"net"
)

type TcpSession struct {
	AbstractSession
	conn    net.Conn
	address string
}

func (s *TcpSession) Write(packet *Packet) error {
	if packet.Data == nil {
		return errors.New("参数错误")
	}
	_, err := s.conn.Write(packet.Data)
	return err
}

func (s *TcpSession) GetAddress() string {
	return s.address
}
func (s *TcpSession) GetKey() any {
	return s.conn
}

type TcpServer struct {
	pattern.AbstractSubject[*Packet]
	address  string
	listener net.Listener
	isOpened bool
	sessions map[net.Conn]any
}

func NewTcpServer(address string) *TcpServer {
	return &TcpServer{address: address, sessions: make(map[net.Conn]any)}
}

func (s *TcpServer) Open() error {
	if s.isOpened {
		return errors.New("服务已打开")
	}
	var err error
	s.listener, err = net.Listen("tcp", s.address)
	if err != nil {
		return err
	}
	s.isOpened = true
	go s.accept()
	return nil
}

func (s *TcpServer) Close() {
	if s.isOpened {
		_ = s.listener.Close()
	}
	for k, _ := range s.sessions {
		_ = k.Close()
	}
	s.sessions = make(map[net.Conn]any)
}

func (s *TcpServer) Write(data *Packet) error {
	if data.Session == nil || len(data.Data) == 0 {
		return errors.New("参数错误")
	}
	err := data.Session.Write(data)
	return err
}

func (s *TcpServer) accept() {
	for s.isOpened {
		conn, err := s.listener.Accept()
		if err != nil {
			break
		}
		go s.read(conn)
	}
}

func (s *TcpServer) read(conn net.Conn) {

	address := conn.RemoteAddr().String()
	session := &TcpSession{conn: conn, address: address}
	s.sessions[conn] = session
	s.Notify(&Packet{Type: PacketTypeConnected, Data: nil, Session: session})
	buffer := make([]byte, 1024*256)
	for s.isOpened {
		n, err := conn.Read(buffer)
		if err != nil {
			if s.isOpened {
				_ = conn.Close()
				s.Notify(&Packet{Type: PacketTypeConnectLost, Session: session})
			}
			break
		}
		data := make([]byte, n)
		copy(data, buffer[:n])
		s.Notify(&Packet{Type: PacketTypeData, Data: data, Session: session})
	}
	delete(s.sessions, conn)
}
